﻿using System.Collections.Generic;
using Socium.Domain;
using Socium.Domain.Collections;
using Socium.Domain.Tests;
using Socium.Presentation;

namespace Socium.Testings {
	class TestingTestsIndexViewModel : IndexViewModelBase<Repository<Test>, TestLineItem> {
		public TestingTestsIndexViewModel(string display_name, Database database, ISelectionSource selection_source, IEnumerable<TestLineItem> childeren) 
			: base(display_name, CreateModel(), childeren) {
			_selection_source = selection_source;
			_database = database;
		}

		public TestingTestsIndexViewModel(string display_name, Database database, ISelectionSource selection_source)
			: base(display_name, CreateModel()) {
			_selection_source = selection_source;
			_database = database;
		}

		readonly ISelectionSource _selection_source;
		readonly Database _database;

		static Repository<Test> CreateModel() {
			return new Repository<Test>();
		}

		protected override void OnItemAdded(Repository<Test> model, TestLineItem child) {
			child.QueryDelete += test => OnDeleteTest(child, test);
		}

		protected override void OnNewChild(Repository<Test> model) {
			var item = (TestLineItem) _selection_source.QueryItem("Select test", _database.Tests.MapLazy(test => new TestLineItem(test)));
			if (item != null) {
				model.Add(item.Model);
				Childeren.Add(item);
			}
		}

		public void Save(ICollection<Test> tests) {
			Model.Apply(tests);
		}

		void OnDeleteTest(TestLineItem item, Test obj) {
			Model.Delete(obj);
			Childeren.Remove(item);
		}
	}

	class Repository<T> {
		readonly ICollection<T> _new_items = new LinkedList<T>();
		readonly ICollection<T> _removed_items = new LinkedList<T>();

		public void Add(T item) {
			_new_items.Add(item);
		}

		public void Delete(T item) {
			if (!_new_items.Remove(item)) {
				_removed_items.Add(item);
			}
		}

		public void Apply(ICollection<T> collection) {
			foreach (var item in _removed_items) {
				collection.Remove(item);
			}

			foreach (var item in _new_items) {
				collection.Add(item);
			}
		}
	}
}
